import urllib, urllib2, cookielib
from xml.dom.minidom import parse, parseString
from settings import *
import logging
import re

notes_cleanup_rex = re.compile(r'((.*?) said:)*(.*)')

def RemoveTags(element, *tags):
    for tag in tags:
        childs = element.getElementsByTagName(tag)
        for c in childs:
            c.parentNode.removeChild(c)

def MakeRequest(url, data = None, method = 'GET', headers = {}):
    _headers = { 'Content-Type': 'application/xml; charset=utf-8' }
    if headers:
        _headers.update(headers)
    req = urllib2.Request(url, data, _headers)
    req.get_method = lambda: method
    try:
        res = urllib2.build_opener().open(req)
        data = res.read()
        try:
            return parseString(data)
        except:
            return data
    except urllib2.HTTPError, e:
        data = e.read()
        logging.warn('Error making request to pivotal tracker')
        logging.warn(data)
        return data

def GetToken(username, password):
    url = '%s/tokens/active' % (BASE_URL, )
    data = urllib.urlencode({ 'username': username, 'password': password })
    headers = { 'Content-Type': 'application/x-www-form-urlencoded' }
    result = MakeRequest(url, data, 'POST', headers)
    try:
        return result.getElementsByTagName('guid')[0].firstChild.data
    except:
        return None

def GetProject(project_id, token):
    url = '%s/projects/%s?token=%s' % (BASE_URL, project_id, token)
    return MakeRequest(url)

def CreateStory(project_id, token, story):
    url = '%s/projects/%s/stories?token=%s' % (BASE_URL, project_id, token)
    return MakeRequest(url, story, 'POST', None)

def GetMemberList(project_id, token):
    url = '%s/projects/%s/memberships?token=%s' % (BASE_URL, project_id, token)
    doc = MakeRequest(url)
    members = []
    for membership in doc.getElementsByTagName('membership'):
        role = membership.getElementsByTagName('role')[0].firstChild.data.strip()
        if role.lower() in ['owner', 'member']:
            name = membership.getElementsByTagName('name')[0].firstChild.data.strip()
            members.append(name)
    return members

def GetIteration(project_id, iteration, token):
    url = '%s/projects/%s/iterations/%s?token=%s' % (BASE_URL, project_id, iteration, token)
    return MakeRequest(url)    

def GetStory(project_id, story_id, token):
    url = '%s/projects/%s/stories/%s?token=%s' % (BASE_URL, project_id, story_id, token)
    return MakeRequest(url)

def GetStories(project_id, token, filters = None):
    url = '%s/projects/%s/stories?token=%s' % (BASE_URL, project_id, token)
    if filters:
        url = '%s&filter=%s' % (url, urllib.quote_plus(filters))
    return MakeRequest(url)

def __get_value(story, tag):
    elements = story.getElementsByTagName(tag)
    if elements:
        element = elements[0]
        if element.firstChild:
            return ",".join(sorted(element.firstChild.data.strip().split(",")))
        else:
            return ''
    else:
        return ''

def UpdateStory(project_id, story_id, token, story):
    if isinstance(story, basestring):
        story = parseString(story).documentElement
    current_story = GetStory(project_id, story_id, token)
    url = '%s/projects/%s/stories/%s?token=%s' % (BASE_URL, project_id, story_id, token)
    params = {}
    for child in story.childNodes:
        if child.nodeType != child.ELEMENT_NODE:
            continue
        if child.tagName.endswith('_at') and not child.childNodes:
            story.removeChild(child)
            continue
        if any(map(lambda n: n.nodeType == n.ELEMENT_NODE, child.childNodes)):
            continue
        elif child.tagName not in['owned_by']:
            key = 'story[%s]' % (child.tagName, )
            value = "".join(map(lambda n: n.data, child.childNodes))
            if not value == __get_value(current_story, child.tagName):
                params[key] = value
                story.removeChild(child)
        else:
            #Owned_by doesn't properly update to '' using parameters
            owner = "".join(map(lambda n: n.data, child.childNodes)).strip()
            if not owner == __get_value(current_story, 'owned_by'):
                doc = '<story><owned_by>%s</owned_by></story>' % owner
                MakeRequest(url, doc, 'PUT', None)
                logging.info('made update')
    if params:
        logging.info(params)
        url = '%s&%s' % (url, urllib.urlencode(params))
        MakeRequest(url, None, 'PUT', None)
        logging.info('made update')
    

def AddComment(project_id, story_id, token, comment):
    current_story = GetStory(project_id, story_id, token)
    notes = current_story.getElementsByTagName('note')
    notes = map(lambda n: n.getElementsByTagName('text')[0].firstChild.data, notes)
    notes = map(lambda n: notes_cleanup_rex.match(n).groups()[2].strip(), notes)
    clean_comment = notes_cleanup_rex.match(comment).groups()[2].strip()
    
    
    if not any(map(lambda n: n == clean_comment, notes)):
        url = '%s/projects/%s/stories/%s/notes?token=%s' % (BASE_URL, project_id, story_id, token)
        commentBody='<note><text>%s</text></note>' % (comment, )
        return MakeRequest(url, commentBody, 'POST')
        logging.info('made_comment')
